package com.zzzzzz.account.user;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;

import javax.annotation.Resource;

import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.authc.credential.PasswordService;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.zzzzzz.common.GlobalConstants;
import com.zzzzzz.core.dao.BaseDao;

@Repository("userDao")
public class UserDao extends BaseDao {

	@Resource
	private JdbcTemplate jdbcTemplate;
	@Resource
	private PasswordService passwordService;
	
	private static final String ADD = 				"insert into user(email, password, username, status, add_dt, upd_dt) values(?, ?, ?, ?, ?, ?)";
	private static final String EDIT_STATUS = 		"update user set status = ?, upd_dt = ? where id = ?";
	private static final String EDIT_PROFILE = 		"update user set username = ?, website = ?, about_me = ?, upd_dt = ? where id = ?";
	private static final String EDIT_PIC_SET = 		"update user set pic_set = ? where id = ?";
	private static final String EDIT_PASSWORD = 	"update user set password = ? where id = ?";
	private static final String EDIT_EMAIL = 		"update user set email = ? where id = ?";
	
	private static final String FIND_BY_ID = 		"select id,email,password,username,about_me,pic_set,website,add_dt,upd_dt,status from user where id = ? and status = ?";
	private static final String FIND_BY_WEBSITE = 	"select id,email,password,username,about_me,pic_set,website,add_dt,upd_dt,status from user where website = ? and status = 0";
	private static final String FIND_BY_EMAIL = 	"select id,email,password,username,about_me,pic_set,website,add_dt,upd_dt,status from user where email = ? and status = 0";
	private static final String FIND_BASE_BY_ID =   "select id,username,pic_set from user where id = ? and status = 0";
	
	protected class UserRowMapper implements RowMapper<User> {
		public User mapRow(ResultSet rs, int rn) throws SQLException {
			User user = new User();
			user.setId(rs.getLong("id"));
			user.setPassword(rs.getString("password"));
			user.setEmail(rs.getString("email"));
			user.setUsername(rs.getString("username"));
			user.setWebsite(rs.getString("website"));
			user.setAboutMe(rs.getString("about_me"));
			user.setPicSet(rs.getBoolean("pic_set"));
			user.setAddDt(rs.getTimestamp("add_dt"));
			user.setUpdDt(rs.getTimestamp("upd_dt"));
			user.setStatus(rs.getInt("status"));
			return user;
		}
	}
	protected class UserBaseRowMapper implements RowMapper<UserBase> {
		public UserBase mapRow(ResultSet rs, int rn) throws SQLException {
			UserBase userBase = new UserBase();
			userBase.setId(rs.getLong("id"));
			userBase.setUsername(rs.getString("username"));
			userBase.setPicSet(rs.getBoolean("pic_set"));
			return userBase;
		}
	}
	
	public void add(User user) throws UserAlreadyExistsException {
		try{
			user.setStatus(GlobalConstants.STATUS.INACTIVE);//未激活
			user.setPassword(passwordService.encryptPassword(user.getPassword()));
			user.setAddDt(new Date());
			user.setUpdDt(new Date());
			
			jdbcTemplate.update(ADD, user.getEmail(), user.getPassword(), user.getUsername(), user.getStatus(), user.getAddDt(), user.getUpdDt());
			Long id = jdbcTemplate.queryForLong("SELECT @@IDENTITY");
			user.setId(id);
		}catch(DuplicateKeyException e){
			throw new UserAlreadyExistsException(user.getEmail());
		}
	}
	
	public User findByEmail(String email) throws NoSuchUserException {
		try {
			return jdbcTemplate.queryForObject(FIND_BY_EMAIL, new UserRowMapper(),email);
		} catch (EmptyResultDataAccessException e) {
			throw new NoSuchUserException(email);
		}
	}
	
	public Boolean isEmailExisting(String email) {
		try {
			this.findByEmail(email);
		} catch (NoSuchUserException e) {
			return false;
		}
		return true;
	}
	
	
	public User findById(Long id, Integer status) {
		return jdbcTemplate.queryForObject(FIND_BY_ID, new UserRowMapper(), id, status);
	}
	
	public User findByIdOrWebsite(String website) throws NoSuchUserException {
		User user = null;
		if(NumberUtils.isNumber(website)){
			user = this.findById(Long.valueOf(website), GlobalConstants.STATUS.NORMAL);
		}else{
			user = jdbcTemplate.queryForObject(FIND_BY_WEBSITE, new UserRowMapper(), website);
		}
		if(user == null) throw new NoSuchUserException(website);
		return user;
	}
	
	public void editStatus(Long id, Integer status) {
		jdbcTemplate.update(EDIT_STATUS, status, new Date(), id);
	}
	
	public void editPassword(Long id, String password) {
		password = passwordService.encryptPassword(password);
		jdbcTemplate.update(EDIT_PASSWORD, password, id);
	}
	
	public void editProfile(Long id, String username, String website, String aboutMe) {
		jdbcTemplate.update(EDIT_PROFILE, username, website, aboutMe, new Date(), id);
	}
	
	public void editEmail(Long id, String email) {
		jdbcTemplate.update(EDIT_EMAIL, email, id);
	}
	
	public void editPicSet(Long id, boolean picSet) {
		jdbcTemplate.update(EDIT_PIC_SET, picSet, id);
	}
	
	public UserBase findUserBaseById(Long id) {
		return jdbcTemplate.queryForObject(FIND_BASE_BY_ID, new UserBaseRowMapper(), id);
	}
	
}